using System;
using System.Collections.Generic;
using System.Reflection;
using fit;

namespace TestUtils
{
	public abstract class DefinitionFixture: ColumnFixture
	{
		protected IDictionary<string, IList<string>> definition;
		protected IList<FieldInfo> fieldsList = new List<FieldInfo>();

		public override void reset()
		{
			SetDefaultValues();
			base.reset();
		}

		protected virtual void SetDefaultValues()
		{
			foreach (FieldInfo fieldInfo in fieldsList)
			{
				fieldInfo.SetValue(this, String.Empty);
			}
		}

		public override void doRows(Parse rows)
		{
		    RegisterFixture();
		    base.doRows(rows);
		}

	    public void RegisterFixture()
	    {
	        CreateDefinitionDictionary();
	        CreateFieldsArray();
	    }

	    protected virtual void AddDefinitionsToContext(Context context)
		{
			foreach (FieldInfo fieldInfo in fieldsList)
			{
				IList<string> fieldValues = definition[fieldInfo.Name];
				fieldValues.Add((string)fieldInfo.GetValue(this));
			}
		}

		protected virtual void CreateDefinitionDictionary()
		{
			string definitonName = GetDefinitonName();
			Context context = ContextManager.TestContext;
			if (context.FixedDefinitions.ContainsKey(definitonName))
			{
				definition = context.FixedDefinitions[definitonName];
			}
			else
			{
				definition = new Dictionary<string, IList<string>>();
				context.FixedDefinitions.Add(definitonName, definition);
			}
		}

		protected virtual void CreateFieldsArray() {
			Type type = GetType();
			FieldInfo[] fields = type.GetFields();
			foreach (FieldInfo field in fields)
			{
				if (field.FieldType.Equals(typeof(string)) && (field.IsPublic))
				{
					AddFieldToFieldsArray(field);
				}
			}
		}

		protected virtual void AddFieldToFieldsArray(FieldInfo field) {
			IList<string> fieldValues;
			if (!definition.ContainsKey(field.Name))
			{
				fieldValues = new List<string>();
				definition.Add(field.Name, fieldValues);
			}
			fieldsList.Add(field);
		}

		protected virtual string GetDefinitonName()
		{
			return GetType().Name;
		}

		public override void execute()
		{
			AddDefinitionsToContext(ContextManager.TestContext);
			base.execute();
		}
	}
}